#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <netdb.h>

#include "socket.h"
#include "logger.h"

int socket_init(socket_t *sock, char *host, int port)
{
	if( !sock || port <= 0 )
	{
		return -1;
	}
	
	memset(sock, 0, sizeof(*sock));
	sock->port = port;
	sock->fd = -1;
	if( host )
	{
		strncpy(sock->host, host, HOST_LEN);
	}
	return 0;
}

int socket_close(socket_t *sock)
{
	if( !sock || sock->fd <0 )
	{
		return -1;
	}
	close(sock->fd);
	sock->fd = -1;
	return 0;
}

int socket_connect(socket_t *sock)
{
	int					sockfd		=	-1;
	int					rv			=	-1;
	struct	addrinfo	hints,*res,*rp;
	char				service[32];
	struct in_addr		inaddr;
	struct sockaddr_in 	addr,*sp;
	char				ipaddr[64];
	
	if( !sock )
	{
		return -1;
	}
	
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	
	if(inet_aton(sock->host, &inaddr))
	{
		hints.ai_flags |=AI_NUMERICHOST;
	}
	snprintf(service, sizeof(service), "%d", sock->port);
	
	if(getaddrinfo(sock->host, service, &hints, &res) != 0)
	{
		log_warn("getaddrinfo falure\n");
		return -2;
	}
	for(rp=res;rp!=NULL;rp=rp->ai_next)
	{
		sp = (struct sockaddr_in *)rp->ai_addr;
		memset( ipaddr, 0, sizeof(ipaddr));
		if( inet_ntop(AF_INET, &sp->sin_addr, ipaddr, sizeof(ipaddr)))
		{
			log_info("host:%s->ipaddr:%s\n",sock->host,ipaddr);
		}

		sockfd=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if( sockfd < 0 )
		{
			log_warn("creat socket error\n");
			rv =-1;
			close(sockfd);
			continue;
		}
		
		rv=connect(sockfd, rp->ai_addr, rp->ai_addrlen);
		if( rv==0 )
		{
			sock->fd = sockfd;
			log_info("connect to server[%d] successfully\n",sock->fd);
			break;
		}
		else
		{
			close(sockfd);
			continue;
		}
	}
	freeaddrinfo(res);
	return rv;
}

int socket_senddata(socket_t *sock, char *data, int bytes)
{
	int					rv			=	-1;
	int					i			=	0;
	int					left_bytes	= 	bytes;
	
	if(	!sock|| !data || bytes < 0)
	{
		return -1;
	}
	
	while(left_bytes > 0)
	{
		rv = write(sock->fd, &data[i], left_bytes);
		if(rv < 0)
		{
			log_warn("socket[%d] write error\n",sock->fd);
			socket_close(sock);
			return -1;
		}
		else if(rv == left_bytes)
		{
			log_info("socket[%d] write %d data over:%s\n",sock->fd,bytes,data);
			return 0;
		}
		else
		{
			i+=rv;
			left_bytes-=rv;
			continue;
		}
	}
	return 0; 
}
int socket_alive(int fd)
{
    struct tcp_info info = {0};  // 使用{0}初始化结构体，确保所有字段都被置零
    int len = sizeof(info);
    int ret = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);

    if (ret < 0) {  // 检查getsockopt是否执行成功
        log_info("getsockopt failed, error: %s\n", strerror(errno));
        return -1;
    }

    if (info.tcpi_state == TCP_ESTABLISHED) {
        return 0;
    } else {
        log_info("disconnect\n");
        return -1;
    }
}

